home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / IRC client Source / ircle sources / IRCChannels.p < prev    next >
Encoding:
Text File  |  1993-07-19  |  9.2 KB  |  449 lines  |  [TEXT/PJMM]

  1. {    ircle - Internet Relay Chat client    }
  2. {    File: IRCChannels    }
  3. {    Copyright © 1992 Olaf Titz (s_titz@ira.uka.de)    }
  4.  
  5. {    This program is free software; you can redistribute it and/or modify    }
  6. {    it under the terms of the GNU General Public License as published by    }
  7. {    the Free Software Foundation; either version 2 of the License, or    }
  8. {    (at your option) any later version.    }
  9.  
  10. {    This program is distributed in the hope that it will be useful,    }
  11. {    but WITHOUT ANY WARRANTY; without even the implied warranty of    }
  12. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    }
  13. {    GNU General Public License for more details.    }
  14.  
  15. {    You should have received a copy of the GNU General Public License    }
  16. {    along with this program; if not, write to the Free Software    }
  17. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    }
  18.  
  19. unit IRCChannels;
  20. { Deals with the window-per-channel interface and all messages to the user. }
  21.  
  22. interface
  23.  
  24. uses
  25.     TCPTypes, TCPStuff, TCPConnections, ApplBase, MsgWindows, IRCGlobals, IRCaux;
  26.  
  27. procedure InitIRCChannels;
  28. { Startup }
  29.  
  30. procedure LineMsg (var s: string);
  31. { Display message in main window }
  32.  
  33. procedure StatusMsg (n: integer);
  34. { Display message from STR# 256 }
  35.  
  36. procedure SetMainTitle (var newtitle: string);
  37. { Call this after changing nick }
  38.  
  39. function DoJoin (var ch: string): MWHndl;
  40. { Open channel window for ch -- this may as well be a queried nick }
  41.  
  42. procedure DoPart (var ch: string);
  43. { Close channel window for ch }
  44.  
  45. procedure partWindow (p: WindowPtr);
  46. { user closing window}
  47.  
  48. procedure ChannelMsg (var ch, msg: string);
  49. { Display msg in the window for channel ch, }
  50. { or in the frontmost window if a ch window does not exist }
  51.  
  52. procedure Message (var msg: string);
  53. { Display msg in current window }
  54.  
  55. procedure Inactive (var ch: string);
  56. { mark a window as inactive }
  57.  
  58. procedure GetAllWindows (channels, queries, chats: boolean; var s: string);
  59. { make list of all active target windows }
  60.  
  61. implementation
  62.  
  63. type
  64.     CPtr = ^Clist;
  65.     Clist = record
  66.             n: CPtr;
  67.             w: MWHndl;
  68.             mp: integer;
  69.         end;
  70.  
  71. {$IFC OLD_PASCAL}
  72. { Notification Manager glue - not needed on new compilers }
  73. type
  74.     NMRec = record
  75.             qLink: QElemPtr;   {next queue entry}
  76.             qType: INTEGER;    {queue type -- ORD(nmType) = 8}
  77.             nmFlags: INTEGER;    {reserved}
  78.             nmPrivate: LONGINT;    {reserved}
  79.             nmReserved: INTEGER;    {reserved}
  80.             nmMark: INTEGER;    {item to mark in Apple menu}
  81.             nmSIcon: Handle;     {handle to small icon}
  82.             nmSound: Handle;     {handle to sound record}
  83.             nmStr: StringPtr;  {string to appear in alert}
  84.             nmResp: ProcPtr;    {pointer to response routine}
  85.             nmRefCon: LONGINT;    {for application use}
  86.         end;
  87.     NMPtr = ^NMRec;
  88.  
  89. var
  90.     mwin: MWHndl;
  91.     CW: Cptr;
  92.     noti: NMRec;
  93.     SIcon, Sound: Handle;
  94.  
  95. function NMInstall (nmReqPtr: QElemPtr): OSErr;
  96. inline
  97.     $205F, $A05E, $3E80;
  98.  
  99. function NMRemove (nmReqPtr: QElemPtr): OSErr;
  100. inline
  101.     $205F, $A05F, $3E80;
  102.  
  103. function SetCurrentA5: longint;
  104. inline
  105.     $2E8D, $2A78, $0904;
  106.  
  107. function SetA5 (newA5: longint): longint;
  108. inline
  109.     $2F4D, $0004, $2A5F;
  110.  
  111. {$ENDC}
  112.  
  113. procedure remove (q: NMPtr);
  114.     var
  115.         ca5: longint;
  116.     begin
  117.         ca5 := setA5(q^.nmRefCon);
  118.         if notified then
  119.             notified := (NMRemove(@noti) <> 0);
  120.         ca5 := setA5(ca5);
  121.     end;
  122.  
  123. procedure NotifyUser (blink, beep, bkgnd: boolean);
  124.     begin
  125.         if blink or beep then begin
  126.             if blink then
  127.                 noti.nmSIcon := SIcon
  128.             else
  129.                 noti.nmSIcon := nil;
  130.             if beep then
  131.                 noti.nmSound := Sound
  132.             else
  133.                 noti.nmSound := nil;
  134.             if bkgnd then
  135.                 noti.nmResp := nil
  136.             else
  137.                 noti.nmResp := @remove;
  138.             if not notified then
  139.                 notified := (NMInstall(@noti) = 0);
  140.         end;
  141.     end;
  142.  
  143. procedure hideit (w: WindowPtr);
  144.     begin
  145.         HideWindow(w)
  146.     end;
  147.  
  148. function DoMSGWindow: boolean;
  149.     begin
  150.         if mwin = nil then begin
  151.             mwin := NewMWindow(CurrentNick, @hideit);
  152.             DoMsgWindow := false
  153.         end
  154.         else begin
  155.             DoMsgWindow := (mwin^^.w <> FrontWindow);
  156.         end;
  157.         ShowWindow(mwin^^.w);
  158.     end;
  159.  
  160. procedure CommonMsg (var m: string; noti: boolean);
  161.     begin
  162.         if logging then
  163.             writeln(logfile, m);
  164.         if noti then
  165.             if inBackground then
  166.                 NotifyUser(default^^.notify[3], default^^.notify[4], true)
  167.             else
  168.                 NotifyUser(default^^.notify[1], default^^.notify[2], false);
  169.     end;
  170.  
  171. procedure LineMsg (var s: string);
  172.     var
  173.         b: boolean;
  174.     begin
  175.         b := DOMSGWindow;
  176.         MWMessage(mwin, s);
  177.         lastWindow := mwin;
  178.         CommonMsg(s, b);
  179.     end;
  180.  
  181. procedure StatusMsg (n: integer);
  182.     var
  183.         s: str255;
  184.         b: boolean;
  185.     begin
  186.         b := DOMsgWindow;
  187.         GetIndString(s, 256, n);
  188.         MWMessage(mwin, s);
  189.     end;
  190.  
  191. procedure SetMainTitle (var newtitle: string);
  192.     begin
  193.         if mwin <> nil then
  194.             SetWTitle(mwin^^.w, newtitle);
  195.         SetItem(GetMHandle(M_WINDOWS), M_WI_MAIN, newtitle);
  196.         EnableItem(GetMHandle(M_WINDOWS), M_WI_MAIN);
  197.     end;
  198.  
  199. procedure NormTitle (var s: string);
  200.     begin
  201.         if s[1] = INACTIVE_PREFIX then begin
  202.             delete(s, 1, 1);
  203.             s[0] := pred(s[0]);
  204.         end
  205.     end;
  206.  
  207.  
  208. function ChannelWindow (var ch: string): MWHndl;
  209.     var
  210.         s: Str255;
  211.         l: CPtr;
  212.     begin
  213.         l := CW;
  214.         NormTitle(ch);
  215.         while l <> nil do begin
  216.             GetWTitle(l^.w^^.w, s);
  217.             NormTitle(s);
  218.             if EqualString(ch, s, false, true) then begin
  219.                 ChannelWindow := l^.w;
  220.                 exit(ChannelWindow)
  221.             end;
  222.             l := l^.n
  223.         end;
  224.         ChannelWindow := nil
  225.     end;
  226.  
  227.  
  228. function activate (var e: EventRecord): boolean;
  229.     var
  230.         p: CPtr;
  231.         s: string;
  232.     begin
  233.         activate := false;
  234.         if odd(e.modifiers) then begin
  235.             p := CW;
  236.             while p <> nil do begin
  237.                 if p^.w^^.w = WindowPtr(e.message) then begin
  238.                     GetWTitle(p^.w^^.w, CurrentTarget);
  239.                     if CurrentTarget[1] = INACTIVE_PREFIX then
  240.                         CurrentTarget := '';
  241.                     UpdateStatusLine;
  242.                     exit(activate)
  243.                 end;
  244.                 p := p^.n
  245.             end;
  246.             currentTarget := '';
  247.             UpdateStatusLine;
  248.         end
  249.     end;
  250.  
  251. function Switcher (var e: EventRecord): boolean;
  252.     var
  253.         i: integer;
  254.     begin
  255.         inBackground := (bitand(e.message, 1) = 0);
  256.         if not InBackground then
  257.             InitCursor;
  258.         if notified then
  259.             i := NMRemove(@noti);
  260.         notified := false;
  261.         Switcher := false
  262.     end;
  263.  
  264. function wmenu (var e: EventRecord): boolean;
  265.     var
  266.         l: CPtr;
  267.         s: str255;
  268.     begin
  269.         case e.message of
  270.             M_WI_CYCLE: 
  271.                 begin
  272.                 SendBehind(FrontWindow, nil);
  273.                 GetWTitle(FrontWindow, s);
  274.                 if s[0] = chr(0) then
  275.                     SendBehind(FrontWindow, nil);
  276.             end;
  277.             M_WI_MAIN: 
  278.                 if mwin <> nil then begin
  279.                     ShowWindow(mwin^^.w);
  280.                     SelectWindow(mwin^^.w);
  281.                 end;
  282.             otherwise
  283.                 begin
  284.                 l := CW;
  285.                 while l <> nil do begin
  286.                     if l^.mp = e.message then begin
  287.                         SelectWindow(l^.w^^.w);
  288.                         leave
  289.                     end;
  290.                     l := l^.n;
  291.                 end;
  292.                 wmenu := true
  293.             end
  294.         end
  295.     end;
  296.  
  297. procedure partWindow (p: WindowPtr); {user closing window}
  298.     var
  299.         p0, p1: CPtr;
  300.         s: str255;
  301.     begin
  302.         GetWTitle(p, s);
  303.         if IsChannel(s) then begin
  304.             s := concat('PART ', s);
  305.             PutLine(s);
  306.         end
  307.         else { inactive/query window }
  308.             begin
  309.             NormTitle(s);
  310.             DoPart(s);
  311.         end;
  312.     end;
  313.  
  314. function DoJoin (var ch: string): MWHndl; {callback from server}
  315.     var
  316.         w: MWHndl;
  317.         l: CPtr;
  318.     begin
  319.         w := ChannelWindow(ch);
  320.         if w = nil then begin
  321.             w := NewMWindow(ch, @partWindow);
  322.             InsMenuItem(GetMHandle(M_WINDOWS), ch, 255);
  323.             new(l);
  324.             l^.n := CW;
  325.             CW := l;
  326.             l^.w := w;
  327.             l^.mp := CountMItems(GetMHandle(M_WINDOWS));
  328.         end
  329.         else begin
  330.             SelectWindow(w^^.w);
  331.             SetWTitle(w^^.w, ch);
  332.         end;
  333.         DoJoin := w
  334.     end;
  335.  
  336. procedure DoPart (var ch: string); {callback from server}
  337.     var
  338.         l, l0: CPtr;
  339.         n: integer;
  340.         s: Str255;
  341.     begin
  342.         l := CW;
  343.         while l <> nil do begin
  344.             GetWTitle(l^.w^^.w, s);
  345.             NormTitle(s);
  346.             if EqualString(ch, s, false, true) then begin
  347.                 n := l^.mp;
  348.                 DelMenuItem(GetMHandle(M_WINDOWS), n);
  349.                 DeleteMWindow(l^.w);
  350.                 if l = CW then
  351.                     CW := l^.n
  352.                 else
  353.                     l0^.n := l^.n;
  354.                 leave;
  355.             end;
  356.             l0 := l;
  357.             l := l0^.n
  358.         end;
  359.         l := CW;
  360.         while l <> nil do begin
  361.             if l^.mp > n then
  362.                 l^.mp := pred(l^.mp);
  363.             l := l^.n
  364.         end;
  365.     end;
  366.  
  367. procedure ChannelMsg (var ch, msg: string);
  368.     var
  369.         m: MWHndl;
  370.         b: boolean;
  371.     begin
  372.         m := ChannelWindow(ch);
  373.         if m = nil then begin
  374.             m := ChannelWindow(CurrentTarget);
  375.             if m = nil then begin
  376.                 b := DOMSGWindow;
  377.                 m := mwin
  378.             end;
  379.         end;
  380.         lastWindow := m;
  381.         MWMessage(m, msg);
  382.         CommonMsg(msg, m^^.w <> FrontWindow);
  383.     end;
  384.  
  385. procedure Message (var msg: string);
  386.     begin
  387.         ChannelMsg(CurrentTarget, msg)
  388.     end;
  389.  
  390.  
  391. procedure InitIRCChannels;
  392.     var
  393.         i: integer;
  394.     begin
  395.         mwin := nil;
  396.         CW := nil;
  397.         i := ApplTask(@activate, activateEvt);
  398.         i := ApplTask(@Switcher, app4Evt);
  399.         i := ApplTask(@wmenu, menuMsg + M_WINDOWS);
  400.         SIcon := GetResource('SICN', 128);
  401.         Sound := GetResource('snd ', 128);
  402.         with noti do begin
  403.             qType := 8;
  404.             nmMark := 1;
  405.             nmStr := nil;
  406.             nmRefCon := SetCurrentA5;
  407.         end;
  408.     end;
  409.  
  410. procedure Inactive (var ch: string);
  411.     var
  412.         m: MWHndl;
  413.         s: string;
  414.     begin
  415.         m := ChannelWindow(ch);
  416.         if m <> nil then begin
  417.             s := concat(INACTIVE_PREFIX, ch, INACTIVE_POSTFIX);
  418.             SetWTitle(m^^.w, s);
  419.             m^^.whenDone := @partWindow; { XX }
  420.         end;
  421.     end;
  422.  
  423. procedure GetAllWindows (channels, queries, chats: boolean; var s: string);
  424.     var
  425.         p: CPtr;
  426.         s0: str255;
  427.         t: (non, chn, que, dcc);
  428.     begin
  429.         p := CW;
  430.         s := '';
  431.         while p <> nil do begin
  432.             GetWTitle(p^.w^^.w, s0);
  433.             if s[1] = DCC_CHAT_PREFIX then
  434.                 t := dcc
  435.             else if IsChannel(s) then
  436.                 t := chn
  437.             else if s[1] = '(' then
  438.                 t := non
  439.             else
  440.                 t := que;
  441.             if (channels and (t = chn)) or (queries and (t = que)) or (chats and (t = dcc)) then
  442.                 s := concat(s, ',', s0);
  443.             p := p^.n;
  444.         end;
  445.         if s[1] = ',' then
  446.             delete(s, 1, 1);
  447.     end;
  448.  
  449. end.